﻿namespace Acoris.Foundation
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    partial class PlainTrieTree
    {
        private readonly object m_lock = new object();

        #region SearchPointer Definition

        /// <summary>
        /// 用于模式匹配的搜索指针
        /// </summary>
        internal struct SearchPointer
        {
            /// <summary>
            /// 
            /// </summary>
            internal Node node;

            /// <summary>
            /// 
            /// </summary>
            internal string source;

            //
            internal int offset;

            internal void Move()
            {
                offset++;
            }

            internal bool Finished()
            {
                return offset == source.Length;
            }
        }

        #endregion

        #region PatternMatch Definition

        /// <summary>
        /// 匹配指定的关键字并返回值
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public Action Match(string pattern)
        {
            // save root Node
            var node = this.root.Clone();
            var sp = new SearchPointer{ node = node,source = pattern};

            for (; !sp.Finished(); sp.Move()) {
                sp.node = sp.node.GetNextNode(sp.source[sp.offset]);
                if (sp.node == null) {
                    break;
                }
            }
            node = sp.node;

            if (node.ended) {
                return node.action;
            }

            return null;
        }

        #endregion

        #region SuffixMatch

        /// <summary>
        /// 对指定的关键字进行前缀匹配
        /// </summary>
        /// <param name="text">指定要进行前缀匹配的关键词</param>
        /// <returns>返回一个集合，该集合中的所有元素均是以指定字符串为公共前缀的单词</returns>
        public IReadOnlyCollection<string> SuffixMatch(string text)
        {
            var node = GetToNode(ref text);
            var sb = new StringBuilder();
            var list = new List<string>();

            if (text.Length == 0) {
                return null;
            }

            sb.Append(text);
            TravelAllSubNode(node, sb, list);

            return list;
        }

        Node GetToNode(ref string text)
        {
            var node = this.root.Clone();
            var length = 0;
            foreach(var input in text) {
                length++;
                var newNode = node.GetNextNode(input);
                if(newNode != null) {
                    node = newNode;
                }
                else {
                    text = text.Substring(0, length);
                    break;
                }
            }
            return node;
        }
        
        void TravelAllSubNode(Node node,StringBuilder stringBuilder,List<string> collection)
        {
            //if(nodeIndex >= node.Count) {
            //    nodeIndex--;
            //    return;
            //}

            if (!node.HasNextState) {
                var text = stringBuilder.ToString();
                collection.Add(text);
                stringBuilder = stringBuilder.Remove(stringBuilder.Length - 1, 1);
                return;
            }
            else {
                for(int i = 0; i < node.Count; i++) {
                    var newNode = node.GetNextNode(i);
                    stringBuilder.Append(newNode.value);
                    TravelAllSubNode(newNode, stringBuilder, collection);
                }
            }
        }

        #endregion
    }
}
